/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ids.dl;

import ids.util.Config;
import ids.util.DataHandler;
import ids.util.ObjectLock;
import java.net.MalformedURLException;
import java.rmi.AccessException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author isuru
 */
public class ClientsHandler implements IClientsHandler{

    volatile Registry[] registries = null;
    ArrayList<IServer> servers = null;

    public ClientsHandler() throws NotBoundException, MalformedURLException 
    {
        servers = new ArrayList<IServer>();
//        ArrayList<String> uriList = Config.getAllUris();
//        for (int i = 0; i < Config.getUriCount(); i++) 
//        {
//            try {
//                try {
//                    servers.add((IServer)Naming.lookup ("//" + uriList.get(i)+ ":" +3232+"/IServer"));
//                } catch (NotBoundException ex) {
//                    Logger.getLogger(ClientsHandler.class.getName()).log(Level.SEVERE, null, ex);
//                } catch (AccessException ex) {
//                    Logger.getLogger(ClientsHandler.class.getName()).log(Level.SEVERE, null, ex);
//                }
//            } catch (RemoteException ex) {
//                Logger.getLogger(ClientsHandler.class.getName()).log(Level.SEVERE, null, ex);
//            }
//        }
    }
    
    
    public String getCoordinatorUri(){
        ArrayList<String> uriList = Config.getAllUris();
        IServer newserver = null;
        for (int i = 0; i < Config.getUriCount(); i++) 
        {
            try 
            {
                newserver = (IServer)Naming.lookup ("//" + uriList.get(i)+ ":" +3232+"/IServer");
                if(!servers.contains(newserver))
                {
                    servers.add(newserver);
                }
            } catch (Exception ex) {
                for(int j =0; j < servers.size(); j++)
                {
                    try {
                        IServer iser = servers.get(j);
                        if(iser.getIp().getHostAddress().equalsIgnoreCase(uriList.get(i)))
                        {
                            servers.remove(iser);
                        }
                    } catch (RemoteException ex1) {
                        Logger.getLogger(ClientsHandler.class.getName()).log(Level.SEVERE, null, ex1);
                    }
                }
            }
        }
        double minCPULoadAverage = 0;
        double tempCPULoadAverage = 0;
        int selectedServerId = 0;
        for(int i = 0; i < servers.size(); i++)
        {
            try {
                tempCPULoadAverage = servers.get(i).voteForCoordinator();
                if(tempCPULoadAverage >= 0)
                {
                    if(i == 0)
                    {
                        minCPULoadAverage = tempCPULoadAverage;
                        selectedServerId = i;
                    }
                    else if(tempCPULoadAverage < minCPULoadAverage)
                    {
                        minCPULoadAverage = tempCPULoadAverage;
                        selectedServerId = i;
                    }
                }
                else
                {
                    break;
                }
            } catch (RemoteException ex) {
                Logger.getLogger(ClientsHandler.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        double min = 0.0;
        if(minCPULoadAverage <= min)
        {
            Random ran = new Random();
            return Config.getAllUris().get(ran.nextInt(Config.getUriCount()));
        }
        else
        {
            return Config.getAllUris().get(selectedServerId);
        }
    }

    public Response doSearch(Request request) throws RemoteException{
        long startTime = System.currentTimeMillis();
        Coordinator coordinator = new Coordinator(this.servers);
        ObjectLock objectLock = new ObjectLock();
        coordinator.doSearch(objectLock, request.getKeyWord(), DataHandler.getFilePaths(), request.getSessionId());
//        synchronized(objectLock)
//        {
//            try 
//            {
//                objectLock.wait();
//            } catch (InterruptedException ex) 
//            {
//                Logger.getLogger(Coordinator.class.getName()).log(Level.SEVERE, null, ex);
//            }
//        }
        long finishedTime = System.currentTimeMillis();
        Response response = new Response();
        response.setSearchedResult(coordinator.getResults());
        response.setResponseTime(finishedTime - startTime);
        return response;
    }

}
